package com.mdd.admin.service.goods.impl;

import cn.hutool.core.bean.BeanUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.google.common.collect.Lists;
import com.google.common.collect.Maps;
import com.mdd.admin.service.category.IGoodsCategoryService;
import com.mdd.admin.service.goods.IGoodsService;
import com.mdd.admin.service.image.IGoodsImageService;
import com.mdd.admin.service.specification.impl.GoodsSpecificationServiceImpl;
import com.mdd.admin.service.unit.IGoodsUnitService;
import com.mdd.admin.validate.common.PageParam;
import com.mdd.admin.validate.goods.GoodsParam;
import com.mdd.admin.vo.goods.GoodsDetailVo;
import com.mdd.admin.vo.goods.GoodsListVo;
import com.mdd.admin.vo.goods.StatisticsGoodsVo;
import com.mdd.admin.vo.specification.GoodsSpecificationListVo;
import com.mdd.common.constant.GlobalConstant;
import com.mdd.common.core.PageResult;
import com.mdd.common.entity.goods.GoodsCategory;
import com.mdd.common.entity.goods.Goods;
import com.mdd.common.entity.image.GoodsImage;
import com.mdd.common.entity.goods.GoodsSpecification;
import com.mdd.common.entity.goods.GoodsUnit;
import com.mdd.common.enums.GoodsCategoryStatusEnum;
import com.mdd.common.mapper.goods.GoodsMapper;
import com.mdd.common.mapper.specification.GoodsSpecificationMapper;
import com.mdd.common.utils.RedisUtil;
import com.mdd.common.utils.StringUtil;
import com.mdd.common.utils.TimeUtil;
import com.mdd.common.utils.UrlUtil;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.stereotype.Service;
import org.springframework.util.Assert;

import javax.annotation.Resource;
import java.io.Serializable;
import java.time.DayOfWeek;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 服务实现类
 */
@Service
@Slf4j
public class GoodsServiceImpl implements IGoodsService {

	@Resource
	GoodsMapper goodsMapper;

	@Resource
	private IGoodsImageService goodsImageService;

	@Resource
	private IGoodsCategoryService categoryService;

	@Resource
	private IGoodsUnitService unitService;


	@Resource
	GoodsSpecificationMapper goodsSpecificationMapper;

	@Resource
	GoodsSpecificationServiceImpl specificationService;

	/**
	 * 服务列表
	 *
	 * @param pageParam 分页参数
	 * @param params    搜索参数
	 * @return PageResult<GoodsListVo>
	 */
	@Override
	public PageResult<GoodsListVo> list(PageParam pageParam, Map<String, String> params) {
		Integer page = pageParam.getPageNo();
		Integer limit = pageParam.getPageSize();

		QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("is_delete", 0);
		queryWrapper.orderByDesc("sort");
		queryWrapper.orderByDesc("create_time");

		goodsMapper.setSearch(queryWrapper, params, new String[]{
				"like:name:str",
				"=:remarks:str",
				"=:categoryId@category_id:long",
				"=:unitId@unit_id:long",
				"=:image:str",
				"=:price:str",
				"=:scribingPrice@scribing_price:str",
				"=:status:int",
				"=:sort:int",
				"=:content:str",
				"=:orderNum@order_num:int",
		});

		IPage<Goods> iPage = goodsMapper.selectPage(new Page<>(page, limit), queryWrapper);
		if (CollectionUtils.isEmpty(iPage.getRecords())) {
			return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), Lists.newArrayList());
		}
		Map<Long, String> categoryMap = this.getCategoryStr(iPage.getRecords());
		List<Long> unitIds = iPage.getRecords().stream().map(Goods::getUnitId).distinct().collect(Collectors.toList());
		Map<Long, String> unitMap = unitService.listByIds(unitIds).stream().collect(Collectors.toMap(item -> item.getId(), item -> item.getName()));
		List<GoodsListVo> list = new LinkedList<>();
		for (Goods item : iPage.getRecords()) {
			GoodsListVo vo = new GoodsListVo();
			BeanUtils.copyProperties(item, vo);
			vo.setCategory(categoryMap.get(item.getCategoryId()));
			vo.setUnit(unitMap.get(item.getUnitId()));
			vo.setImage(UrlUtil.toAbsoluteUrl(item.getImage()));
			vo.setStatusDesc(GoodsCategoryStatusEnum.getMap().get(vo.getStatus()));
			vo.setCreateTime(TimeUtil.timestampToDate(item.getCreateTime()));
			vo.setUpdateTime(TimeUtil.timestampToDate(item.getUpdateTime()));
			list.add(vo);
		}
		return PageResult.iPageHandle(iPage.getTotal(), iPage.getCurrent(), iPage.getSize(), list);
	}

	@Override
	public StatisticsGoodsVo statistics(Map<String, String> params) {
		QueryWrapper<Goods> queryWrapper = new QueryWrapper<>();
		queryWrapper.eq("is_delete", 0);

		goodsMapper.setSearch(queryWrapper, params, new String[]{
				"like:name:str",
				"=:remarks:str",
				"=:categoryId@category_id:long",
				"=:unitId@unit_id:long",
				"=:image:str",
				"=:price:str",
				"=:scribingPrice@scribing_price:str",
				"=:status:int",
				"=:sort:int",
				"=:content:str",
				"=:orderNum@order_num:int",
		});
		List<Goods> goods = goodsMapper.selectList(queryWrapper);
		StatisticsGoodsVo statisticsGoodsVo = new StatisticsGoodsVo();
		if (CollectionUtils.isEmpty(goods)) {
			return statisticsGoodsVo;
		}
		long warehouseCount = goods.stream().map(Goods::getStatus).filter(item -> GoodsCategoryStatusEnum.WAREHOUSE.getStatus() == item).count();
		long inSalesCount = goods.stream().map(Goods::getStatus).filter(item -> GoodsCategoryStatusEnum.IN_SALES.getStatus() == item).count();
		statisticsGoodsVo.setAllCount(goods.size());
		statisticsGoodsVo.setInSalesCount((int) inSalesCount);
		statisticsGoodsVo.setWarehouseCount((int) warehouseCount);
		return statisticsGoodsVo;
	}

	@Override
	public List<GoodsDetailVo> detailByIds(List<Long> goodsIds) {
		List<GoodsDetailVo> list = Lists.newArrayList();
		if (CollectionUtils.isEmpty(goodsIds)) {
			return list;
		}
		for (Long goodsId : goodsIds) {
			list.add(this.detail(goodsId));
		}
		return list;
	}

	@Override
	public Goods getById(Long goodsId) {
		return goodsMapper.selectById(goodsId);
	}

	private Map<Long, String> getCategoryStr(List<Goods> goodsList) {
		Map<Long, String> map = Maps.newHashMap();
		List<Long> categoryIds = goodsList.stream().map(Goods::getCategoryId).distinct().collect(Collectors.toList());
		List<GoodsCategory> categoryList = categoryService.listByIds(categoryIds);
		List<Long> pidIds = categoryList.stream().map(GoodsCategory::getPid).filter(item -> item != null).collect(Collectors.toList());
		Map<Long, String> parentMap = categoryService.listByIds(pidIds).stream().collect(Collectors.toMap(item -> item.getId(), item -> item.getName()));
		for (GoodsCategory goodsCategory : categoryList) {
			if (map.containsKey(goodsCategory.getId())) {
				continue;
			}
			StringBuilder sb = new StringBuilder();
			if (parentMap.containsKey(goodsCategory.getPid())) {
				sb.append(parentMap.get(goodsCategory.getPid())).append("/");
			}
			sb.append(goodsCategory.getName());
			map.put(goodsCategory.getId(), sb.toString());
		}
		return map;
	}

	/**
	 * 服务详情
	 *
	 * @param id 主键参数
	 * @return Goods
	 */
	@Override
	public GoodsDetailVo detail(Long id) {
		Goods model = goodsMapper.selectOne(
				new QueryWrapper<Goods>()
						.eq("id", id)
						.last("limit 1"));

		Assert.notNull(model, "数据不存在");

		GoodsDetailVo vo = new GoodsDetailVo();
		BeanUtils.copyProperties(model, vo);
		vo.setCreateTime(TimeUtil.timestampToDate(model.getCreateTime()));
		vo.setImage(UrlUtil.toAbsoluteUrl(model.getImage()));
		// 轮播图
		List<GoodsImage> imageList = goodsImageService.listByGoodsId(model.getId());
		if (CollectionUtils.isNotEmpty(imageList)) {
			List<String> images = Lists.newArrayList();
			for (GoodsImage image : imageList) {
				images.add(UrlUtil.toAbsoluteUrl(image.getUri()));
			}
			vo.setGoodsImageList(images);
		}
		// 单位
		GoodsUnit goodsUnit = unitService.getById(model.getUnitId());
		vo.setUnit(goodsUnit.getName());
		// 服务分类
		Map<Long, String> categoryMap = this.getCategoryStr(Lists.newArrayList(model));
		vo.setCategory(categoryMap.get(model.getCategoryId()));
		//状态
		vo.setStatusDesc(GoodsCategoryStatusEnum.getMap().get(model.getStatus()));
		List<GoodsSpecification> goodsSpecifications = goodsSpecificationMapper.selectList(new LambdaQueryWrapper<GoodsSpecification>().eq(GoodsSpecification::getGoodsId, model.getId()));
		List<GoodsSpecificationListVo> list = goodsSpecifications.stream().map(it -> {
			GoodsSpecificationListVo goodsSpecificationListVo = new GoodsSpecificationListVo();
			BeanUtils.copyProperties(it, goodsSpecificationListVo);
			return goodsSpecificationListVo;
		}).collect(Collectors.toList());
		vo.setGoodsSpecificationListVos(list);
		vo.setCarousel(model.getCarousel());
		vo.setIsBuy(model.getIsBuy());
		vo.setBuyNum(model.getBuyNum());
		vo.setBuyPeopleNum(model.getBuyPeopleNum());
		vo.setBuyStartTime(model.getBuyStartTime());
		vo.setBuyNumber(model.getBuyNumber());
		return vo;
	}

	/**
	 * 服务新增
	 *
	 * @param goodsParam 参数
	 */
	@Override
	public void add(GoodsParam goodsParam) {
		LambdaQueryWrapper<Goods> lambdaQueryWrapper = new LambdaQueryWrapper<>();
		lambdaQueryWrapper.eq(Goods::getName, goodsParam.getName());
		lambdaQueryWrapper.eq(Goods::getIsDelete, GlobalConstant.NOT_DELETE);
		lambdaQueryWrapper.eq(Goods::getCategoryId, goodsParam.getCategoryId());
		lambdaQueryWrapper.last("limit 1");
		Goods goods = goodsMapper.selectOne(lambdaQueryWrapper);
		Assert.isNull(goods, "此服务名称已存在,请重新输入!");
		Goods model = new Goods();
		model.setName(goodsParam.getName());
		model.setRemarks(goodsParam.getRemarks());
		model.setCategoryId(goodsParam.getCategoryId());
		model.setUnitId(goodsParam.getUnitId());
		model.setIntegral(goodsParam.getIntegral());
		model.setOutNumber(goodsParam.getOutNumber());
		model.setCarousel(goodsParam.getCarousel());
		List<String> urlList = Lists.newArrayList();
		if (StringUtil.isNotEmpty(goodsParam.getImage())) {
			String[] split = StringUtil.split(goodsParam.getImage(), ",");
			for (String uri : split) {
				urlList.add(UrlUtil.toRelativeUrl(uri));
			}
			model.setImage(urlList.get(0));
		}
		model.setPrice(goodsParam.getPrice());
		model.setScribingPrice(goodsParam.getScribingPrice());
		model.setStatus(goodsParam.getStatus());
		model.setSort(goodsParam.getSort());
		model.setContent(goodsParam.getContent());
		model.setCreateTime(TimeUtil.timestamp());
		model.setUpdateTime(TimeUtil.timestamp());
		model.setIsManualDispatch(goodsParam.getIsManualDispatch());
		model.setIsBuy(goodsParam.getIsBuy());
		model.setBuyNum(goodsParam.getBuyNum());
		model.setBuyPeopleNum(goodsParam.getBuyPeopleNum());
		model.setBuyStartTime(goodsParam.getBuyStartTime() * 24 * 60 * 60);
		model.setBuyNumber(goodsParam.getBuyNumber());
		//model.setOrderNum(goodsParam.getOrderNum());
		goodsMapper.insert(model);
		// 保存图片
		Long goodsId = model.getId();
		goodsImageService.batchAdd(goodsId, urlList);
	}

	/**
	 * 服务编辑
	 *
	 * @param goodsParam 参数
	 */
	@Override
	public void edit(GoodsParam goodsParam) {
		Goods model = goodsMapper.selectOne(
				new QueryWrapper<Goods>()
						.eq("id", goodsParam.getId())
						.last("limit 1"));

		Assert.notNull(model, "数据不存在!");

		model.setId(goodsParam.getId());
		model.setName(goodsParam.getName());
		model.setRemarks(goodsParam.getRemarks());
		model.setIsManualDispatch(goodsParam.getIsManualDispatch());
		model.setCategoryId(goodsParam.getCategoryId());
		model.setUnitId(goodsParam.getUnitId());
		model.setIntegral(goodsParam.getIntegral());
		model.setOutNumber(goodsParam.getOutNumber());
		model.setCarousel(goodsParam.getCarousel());
		if (StringUtils.isNotEmpty(goodsParam.getImage())) {
			List<String> imagesList = Lists.newArrayList();
			String[] imagesArr = StringUtils.split(goodsParam.getImage(), ",");
			for (String image : imagesArr) {
				imagesList.add(UrlUtil.toRelativeUrl(image));
			}
			model.setImage(imagesList.get(0));
			// 保存轮播图
			goodsImageService.delByGoodIds(model.getId());
			goodsImageService.batchAdd(model.getId(), imagesList);
		}
		model.setPrice(goodsParam.getPrice());
		model.setScribingPrice(goodsParam.getScribingPrice());
		model.setStatus(goodsParam.getStatus());
		model.setSort(goodsParam.getSort());
		model.setContent(goodsParam.getContent());
		model.setIsBuy(goodsParam.getIsBuy());
		model.setBuyNum(goodsParam.getBuyNum());
		model.setBuyPeopleNum(goodsParam.getBuyPeopleNum());
		model.setBuyNumber(goodsParam.getBuyNumber());
		if (Objects.nonNull(goodsParam.getBuyStartTime())) {
			model.setBuyStartTime(goodsParam.getBuyStartTime());
		}
		//model.setOrderNum(goodsParam.getOrderNum());
		//修改服务规格名称
		List<GoodsSpecification> goodsSpecifications = goodsSpecificationMapper.selectList(new LambdaQueryWrapper<GoodsSpecification>().eq(GoodsSpecification::getGoodsId, model.getId()));
		goodsSpecifications.forEach(it -> {
			it.setGoodsName(model.getName());
		});
		specificationService.saveOrUpdateBatch(goodsSpecifications);
		goodsMapper.updateById(model);
	}

	@Override
	public void del(List<Long> ids) {
		List<Goods> modelList = goodsMapper.selectList(
				new QueryWrapper<Goods>()
						.in("id", ids));

		Assert.notNull(modelList, "数据不存在!");
		for (Goods goods : modelList) {
			goods.setIsDelete(GlobalConstant.DELETE);
			goods.setDeleteTime(TimeUtil.timestamp());
			goodsMapper.updateById(goods);
		}
	}

	@Override
	public void updateStatus(List<Long> ids, Integer status) {
		List<Goods> modelList = goodsMapper.selectList(
				new QueryWrapper<Goods>()
						.in("id", ids));
		Assert.notNull(modelList, "数据不存在!");
		for (Goods goods : modelList) {
			goods.setStatus(status);
			goods.setUpdateTime(TimeUtil.timestamp());
			goodsMapper.updateById(goods);
		}
	}

	/**
	 * 该方法是添加今日特价商品
	 *
	 * @param map 今日特价参数
	 */
	@Override
	public void addTodaySpecials(Map<String, GoodsParam> map) {
		String key = "todaySpecials";
		HashMap<String, Object> hashMap = new HashMap<>();
		map.forEach((k, v) -> {
			DayOfWeek.of(Integer.parseInt(k));
			Object o = goodsMapper.selectById(v.getId());
			Assert.notNull(o, "没有该服务id： " + v);
			hashMap.put(k, v.getId());
		});
		RedisUtil.hmSet(key, hashMap);
	}

	@Override
	public Map<String, GoodsDetailVo> selectTodaySpecials() {
		String key = "todaySpecials";
		Map<Object, Object> map = RedisUtil.hmGet(key);
		Map<String, GoodsDetailVo> mapReturn = new HashMap<>();
		for (int i = 1; i <= 7; i++) {
			Object o = map.get(i + "");
			if(o == null) {
				mapReturn.put(i+"", null);
				continue;
			}
			Goods goods = goodsMapper.selectById((Serializable) o);
			Assert.notNull(goods, "没有改服务id" + o);
			GoodsDetailVo goodsDetailVo = new GoodsDetailVo();
			BeanUtil.copyProperties(goods, goodsDetailVo);
			mapReturn.put(i+"", goodsDetailVo);
		}
		return mapReturn;
	}
}
